package com.yunhe.merchants.service.impl;

import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

import com.alibaba.excel.EasyExcel;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.yunhe.common.exception.ArgumentErrorException;
import com.yunhe.common.filter.ServerContextHolder;
import com.yunhe.common.listener.UploadDataListener;
import com.yunhe.common.model.ResultObject;
import com.yunhe.common.model.authority.Organization;
import com.yunhe.common.model.mybatis.PageResult;
import com.yunhe.common.util.DateTimeUtils;
import com.yunhe.common.util.RedisClient;
import com.yunhe.common.util.StringUtil;
import com.yunhe.merchants.client.AuthorityClient;
import com.yunhe.merchants.constant.MyProjectConsts;
import com.yunhe.merchants.domain.*;
import com.yunhe.merchants.model.DataProjectCondition;
import com.yunhe.merchants.model.DataProjectUpload;
import com.yunhe.merchants.repository.*;
import com.yunhe.merchants.service.IDataPlanProjectService;
import com.yunhe.merchants.service.IMyProjectService;
import com.yunhe.merchants.service.IDataProjectService;
import com.yunhe.merchants.util.BeansUtil;
import com.yunhe.merchants.util.IdUtils;
import com.yunhe.merchants.util.MyHeaderUtil;
import com.yunhe.common.util.CollectionUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import com.yunhe.merchants.service.IDataProjectService;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * 经理项目池与公共商机库
 * @author hetao
 * @date 2021/05/10
 */
@Service(value = "dataProjectService")
public class DataProjectServiceImpl implements IDataProjectService {

    private static final Logger logger = LoggerFactory.getLogger(DataProjectServiceImpl.class);

    @Autowired
    private IDataProjectRepository dataProjectDAO;

    @Autowired
    private RedisClient redisClient;

    @Autowired
    private MyHeaderUtil myHeaderUtil;

    @Autowired
    private AuthorityClient authorityClient;

    @Autowired
    private MyProjectRepository myProjectRepository;

    @Autowired
    private IDataHistoryProjectStatusRepository dataHistoryProjectStatusRepository;

    @Resource(name = "myProjectServiceImpl")
    private IMyProjectService myProjectService;

    @Autowired
    private IDataPlanProjectService dataPlanProjectService;

    @Override
    public void deleteDataProject(List<String> ids) throws ArgumentErrorException {
        Long userId = myHeaderUtil.getHeaderUser();
        if(userId == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        if(CollectionUtil.isNotEmpty(ids)){
            for (String id : ids) {
                dataProjectDAO.updateIsDeleteBId(id,userId);
            }
        }
    }

    @Override
    public PageResult findProjectByCondition(DataProjectCondition dataProjectCondition) throws ArgumentErrorException {
        PageResult result = null;
        Long userId = myHeaderUtil.getHeaderUser();
        if(userId == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        //查询当前登录人的组织以及子组织
        subOrg(userId,dataProjectCondition);
        PageHelper.startPage(dataProjectCondition.getPage(),dataProjectCondition.getSize());
        List<DataProject> dataProjects = new ArrayList<>();
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        if(StringUtil.isEmpty(projectCode)){
            throw new ArgumentErrorException("请选择项目进行操作！");
        }
        dataProjectCondition.setStationId(Long.valueOf(projectCode));
        //查询关键字
        dataProjects = getDataProject(dataProjectCondition);
        PageInfo<DataProject> pageInfo = new PageInfo<>(dataProjects);
        result = new PageResult(dataProjectCondition.getPage(),dataProjectCondition.getSize(), (int) pageInfo.getTotal(),dataProjects);
        return result;
    }

    private List<DataProject> getDataProject(DataProjectCondition dataProjectCondition){
        List<DataProject> dataProjects = new ArrayList<>();
        if(StringUtil.isEmpty(dataProjectCondition.getKeyWords())){
            dataProjects  = dataProjectDAO.findProjectByConditionWithOutKeyWords(dataProjectCondition);
        }else {
            //当关键字搜索不为空时，先查询手机号 在查询客户信息  在查询企业名称
            if(StringUtil.isPhoneNumber(dataProjectCondition.getKeyWords())){
                dataProjects  = dataProjectDAO.findProjectByConditionWithCustTel(dataProjectCondition);
                if(CollectionUtil.isEmpty(dataProjects)){
                    dataProjects  = dataProjectDAO.findProjectByConditionWithCustName(dataProjectCondition);
                    if(CollectionUtil.isEmpty(dataProjects)){
                        dataProjects  = dataProjectDAO.findProjectByConditionWithCompanyName(dataProjectCondition);
                    }
                }
            }else {
                dataProjects  = dataProjectDAO.findProjectByConditionWithCustName(dataProjectCondition);
                if(CollectionUtil.isEmpty(dataProjects)){
                    dataProjects  = dataProjectDAO.findProjectByConditionWithCompanyName(dataProjectCondition);
                }
            }
        }
        return dataProjects;
    }

    @Override
    public DataProject createDataProject(DataProject dataProject) throws ArgumentErrorException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        dataProject.setId(IdUtils.getId());
        dataProject.setCreateTime(new Date());
        dataProject.setUpdateTime(new Date());
        dataProject.setUpdater(headerUser);
        dataProject.setProjectStatus(MyProjectConsts.COMPANY_STATUS.ToBeAssigned.value());
        String projectCode = ServerContextHolder.getContext().getProjectCode();
        if(StringUtil.isEmpty(projectCode)){
            throw new ArgumentErrorException("请选择项目进行操作！");
        }
        dataProject.setStationId(Long.valueOf(projectCode));
        dataProjectDAO.createDataProject(dataProject);
        return dataProject;
    }

    @Override
    public DataProject getDataPorjectById(String id) {
        return dataProjectDAO.searchDataProjectByPrimaryKey(id);
    }

    @Override
    public PageResult getHistoryStatus(String id, int page, int size) {
        PageResult result = null;
        PageHelper.startPage(page,size);
        List<DataHistoryProjectStatus> dataHistoryProjectStatusList= dataHistoryProjectStatusRepository.getHistoryStatusByBusinessId(id);
        PageInfo<DataHistoryProjectStatus> pageInfo = new PageInfo<>(dataHistoryProjectStatusList);
        result = new PageResult(page,size, (int) pageInfo.getTotal(),dataHistoryProjectStatusList);
        return result;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void allocationProjects(String ids, Long salesman, Long deptId) throws ArgumentErrorException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String[] idArray = ids.split(",");
        List<String> idList = Arrays.asList(idArray);
        List<DataProject> dataProjects = dataProjectDAO.getDataProejctByIds(idList);
        if(CollectionUtil.isNotEmpty(dataProjects)){
            List<DataProject> collect = dataProjects.stream().filter(dataProject -> {
                return !StringUtil.isEmpty(dataProject.getPlanId());
            }).collect(Collectors.toList());
            myProjectService.insertBatch(dataProjects.stream().map(e ->{
                MyProject intentionProject = new MyProject();
                BeanUtils.copyProperties(e,intentionProject);
                intentionProject.setId(null);
                intentionProject.setUpdater(headerUser);
                intentionProject.setEntryPerson(e.getEntryPerson());
                intentionProject.setEntryDept(e.getEntryDept());
                intentionProject.setResponsibleDept(deptId);
                intentionProject.setPrincipal(salesman);
                intentionProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Intention.value());
                intentionProject.setLeavingReason(null);
                intentionProject.setLatestDestination(null);
                intentionProject.setCreateTime(new Date());
                intentionProject.setUpdateTime(new Date());
                intentionProject.setBusinessId(e.getId());
                intentionProject.setFirstSource(e.getPlanId());
                intentionProject.setLastSource(e.getDataType());
                return intentionProject;
            }).collect(Collectors.toList()));
            //删除项目池数据
            deleteDataProject(idList,headerUser);
            //记录项目池数据变更的状态
            recordHistory(idList,headerUser,MyProjectConsts.COMPANY_STATUS.Intention.value());
            //修改策划部状态
            if(CollectionUtil.isNotEmpty(collect)){
                List<String> plannIds = collect.stream().map(DataProject::getPlanId).collect(Collectors.toList());
                dataPlanProjectService.updateDataPlanProject(plannIds,MyProjectConsts.COMPANY_STATUS.Intention.value(),
                        deptId,salesman);
            }
        }

    }

    private void deleteDataProject(List<String> ids, Long headerUser) {
        if(CollectionUtil.isNotEmpty(ids)){
            for (String id : ids) {
                dataProjectDAO.updateIsDeleteBId(id,headerUser);
            }
        }
    }

    @Override
    public void overt(String ids) throws ArgumentErrorException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String[] idArray = ids.split(",");
        List<String> idList = Arrays.asList(idArray);
        dataProjectDAO.updateDataProjectByIds(idList,MyProjectConsts.COMPANY_STATUS.ToBeClaimed.value(),
                MyProjectConsts.DATA_TYPE.PublicBusinessOpportunityBank.value(),new Date(),headerUser);
        //记录项目池数据变更的状态
        recordHistory(idList,headerUser,MyProjectConsts.COMPANY_STATUS.ToBeClaimed.value());
    }

    /**
     * 记录项目池数据变更的状态
     * @param ids
     * @param headerUser
     * @param projectStatus
     */
    private void recordHistory(List<String> ids, Long headerUser,String projectStatus) {
        if(CollectionUtil.isNotEmpty(ids)){
            dataHistoryProjectStatusRepository.insertBatch(ids.stream().map(e -> {
                DataHistoryProjectStatus dataHistoryProjectStatus = new DataHistoryProjectStatus();
                dataHistoryProjectStatus.setBusinessId(e);
                dataHistoryProjectStatus.setOperator(headerUser);
                dataHistoryProjectStatus.setOperatingTime(new Date());
                dataHistoryProjectStatus.setStatus(projectStatus);
                return dataHistoryProjectStatus;
            }).collect(Collectors.toList()));
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void moveOut(String id) throws ArgumentErrorException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String orgIdStr = redisClient.get("Org:" + headerUser);
        //新增到历史项目
        DataProject dataProject = dataProjectDAO.searchDataProjectByPrimaryKey(id);
        MyProject historyProject = new MyProject();
        BeanUtils.copyProperties(dataProject,historyProject);
        historyProject.setId(null);
        historyProject.setCreateTime(new Date());
        historyProject.setUpdateTime(new Date());
        historyProject.setUpdater(headerUser);
        historyProject.setEntryDept(Long.parseLong(orgIdStr.split("-")[0]));
        historyProject.setEntryPerson(headerUser);
        historyProject.setBusinessId(dataProject.getId());
        historyProject.setCompanyStatus(MyProjectConsts.COMPANY_STATUS.Leave.value());
        myProjectRepository.insert(historyProject);
        //移除项目池
        deleteDataProject(Arrays.asList(id));

        //记录项目池数据变更的状态
        recordHistory(Arrays.asList(id),headerUser,MyProjectConsts.COMPANY_STATUS.Leave.value());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void claim(String ids) throws ArgumentErrorException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String orgIdStr = redisClient.get("Org:" + headerUser);
        allocationProjects(ids,headerUser,Long.parseLong(orgIdStr.split("-")[0]));
    }

    @Override
    public void uploadManageProject(MultipartFile file) throws ArgumentErrorException, IOException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String orgIdStr = redisClient.get("Org:" + headerUser);
        Long orgId = Long.parseLong(orgIdStr.split("-")[0]);
        EasyExcel.read(file.getInputStream(), DataProjectUpload.class,
                new UploadDataListener(this,file.getOriginalFilename(),headerUser,
                        orgId,MyProjectConsts.DATA_TYPE.ManagerProjectPool.value())).sheet().doRead();
    }

    @Override
    public void upload(List<DataProjectUpload> dataProejctUploads, Long userId,Long orgId,String dataType) throws ArgumentErrorException {
        List<DataProject> dataProjects = new ArrayList<>();
        //upload转Do
        convertUploadToDo(dataProejctUploads,dataProjects,userId,orgId,dataType);
        //批量插入
        if(CollectionUtil.isNotEmpty(dataProjects)){
            dataProjectDAO.insertBatch(dataProjects);
        }
        logger.info("导入{}条数据进入数据库",dataProjects.size());
    }

    @Override
    public void uploadPublicProject(MultipartFile file) throws ArgumentErrorException, IOException {
        Long headerUser = myHeaderUtil.getHeaderUser();
        if(headerUser == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        String orgIdStr = redisClient.get("Org:" + headerUser);
        Long orgId = Long.parseLong(orgIdStr.split("-")[0]);
        EasyExcel.read(file.getInputStream(), DataProjectUpload.class,
                new UploadDataListener(this,file.getOriginalFilename(),headerUser,
                        orgId,MyProjectConsts.DATA_TYPE.PublicBusinessOpportunityBank.value())).sheet().doRead();
    }

    @Override
    public List<DataProject> exportManageProject(String ids, DataProjectCondition dataProjectCondition) throws ArgumentErrorException {
        if(!StringUtil.isEmpty(ids)){
            String[] split = ids.split(",");
            dataProjectCondition.setIds(Arrays.asList(split));
        }
        Long userId = myHeaderUtil.getHeaderUser();
        if(userId == null){
            throw new ArgumentErrorException("登录信息已失效,请重新登录");
        }
        //查询当前登录人的组织以及子组织
        subOrg(userId,dataProjectCondition);
        List<DataProject> dataProjects = getDataProject(dataProjectCondition);
        return dataProjects;
    }

    @Override
    public void batchCreate(List<DataProject> dataProjects) {
        dataProjectDAO.insertBatch(dataProjects);
    }

    @Override
    public void back(MyProject p, String dataType) {
        DataProject dataProject = new DataProject();
        dataProject.setId(p.getBusinessId());
        dataProject.setLeavingReason(p.getLeavingReason());
        dataProject.setLatestDestination(p.getLatestDestination());
        dataProject.setRemark(p.getRemark());
        dataProject.setDataType(dataType);
        dataProject.setUpdater(p.getEntryPerson());
        dataProjectDAO.updateDataProject(dataProject);
    }

    @Override
    public void updateDataProjectByPlanId(DataPlanProject dataPlanProject) {
        DataProject dataProject = new DataProject();
        BeanUtils.copyProperties(dataPlanProject,dataProject);
        dataProject.setUpdateTime(new Date());
        dataProject.setDataType(MyProjectConsts.DATA_TYPE.ManagerProjectPool.value());
        dataProject.setPlanId(dataPlanProject.getId());
        dataProjectDAO.updateDataProjectByPlanId(dataProject);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backCreate(MyProject p, String dataType) {
        DataProject dataProject = new DataProject();
        dataProject.setId(p.getBusinessId());
        dataProject.setCompanyName(p.getCompanyName());
        dataProject.setCustName(p.getCustName());
        dataProject.setCustTel(p.getCustTel());
        dataProject.setIndustryType(p.getIndustryType());
        dataProject.setDataSource(p.getDataSource());
        dataProject.setProjectStatus(MyProjectConsts.COMPANY_STATUS.ToBeAssigned.value());
        dataProject.setPlanId(p.getFirstSource());
        dataProject.setLeavingReason(p.getLeavingReason());
        dataProject.setLatestDestination(p.getLatestDestination());
        dataProject.setRemark(p.getRemark());
        dataProject.setDataType(dataType);
        dataProject.setCreateTime(new Date());
        dataProject.setUpdateTime(new Date());
        dataProject.setEntryDept(p.getEntryDept());
        dataProject.setEntryPerson(p.getEntryPerson());
        //dataProject.setUpdater(p.getEntryPerson());
        dataProjectDAO.createDataProject(dataProject);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void backUpDateOrCreate(MyProject p) {
        if(StringUtil.isEmpty(p.getLastSource())){
            backCreate(p,MyProjectConsts.DATA_TYPE.ManagerProjectPool.value());
        }else {
            if (MyProjectConsts.Source.Public.value().equals(p.getLastSource())){
                //返回公共商机库
                back(p,MyProjectConsts.DATA_TYPE.PublicBusinessOpportunityBank.value());
            }else {
                //返回经理项目池
                back(p,MyProjectConsts.DATA_TYPE.ManagerProjectPool.value());
            }
        }
        myProjectService.delete(p.getId());
    }

    private void convertUploadToDo(List<DataProjectUpload> dataProejctUploads, List<DataProject> dataProjects, Long userId, Long orgId,String dataType) throws ArgumentErrorException {
        if(CollectionUtil.isNotEmpty(dataProejctUploads)){
            String projectCode = ServerContextHolder.getContext().getProjectCode();
            if(StringUtil.isEmpty(projectCode)){
                throw new ArgumentErrorException("请选择项目进行操作！");
            }
            List<DataProject> collect = dataProejctUploads.stream().map(e -> {
                DataProject dataProject = new DataProject();
                dataProject.setId(IdUtils.getId());
                BeanUtils.copyProperties(e, dataProject);
                dataProject.setCreateTime(new Date());
                if (MyProjectConsts.DATA_TYPE.ManagerProjectPool.value().equals(dataType)) {
                    dataProject.setProjectStatus(MyProjectConsts.COMPANY_STATUS.ToBeAssigned.value());
                } else if (MyProjectConsts.DATA_TYPE.PublicBusinessOpportunityBank.value().equals(dataType)) {
                    dataProject.setProjectStatus(MyProjectConsts.COMPANY_STATUS.ToBeClaimed.value());
                }
                dataProject.setStationId(Long.valueOf(projectCode));
                dataProject.setEntryDept(orgId);
                dataProject.setEntryPerson(userId);
                dataProject.setDataType(dataType);
                dataProject.setUpdater(userId);
                dataProject.setUpdateTime(new Date());
                return dataProject;
            }).collect(Collectors.toList());
            dataProjects.addAll(collect);
        }
    }


    /**
     * 查询当前登录人的组织以及子组织
     * @param userId
     * @param dataProjectCondition
     */
    private void subOrg(Long userId, DataProjectCondition dataProjectCondition) {
        String orgIdStr = redisClient.get("Org:" + userId);
        if(dataProjectCondition.getResponsibleDept() != null){
            orgIdStr = dataProjectCondition.getResponsibleDept()+"-"+orgIdStr.split("-")[1];
        }
        //获取当前登录人的组织
        if(!StringUtil.isEmpty(orgIdStr)){
            //查询当前组织以及子组织信息
            ResponseEntity<ResultObject> responseEntity = authorityClient.getSubOrg(orgIdStr);
            if(responseEntity != null){
                if(responseEntity.getStatusCode().is2xxSuccessful()){
                    Object results = responseEntity.getBody().getResults();
                    List<Organization> organizations = JSON.parseArray(JSON.toJSONString(results),Organization.class);
                    if (CollectionUtil.isNotEmpty(organizations)) {
                        List<Long> orgIds = organizations.stream().filter(organization -> organization.getId() != null)
                                .map(Organization::getId).collect(Collectors.toList());
                        dataProjectCondition.setOrgIds(orgIds);
                    }
                }
            }
        }
    }

}
